/**
 * Copyright (c) Software Institude of PKU
 * All rights reserved. 
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 */
package edu.pku.sei.modeler.model.uml.Kernel;
// imports:
import java.util.List;

import org.w3c.dom.Element;

import edu.pku.sei.gefcommon.descriptor.annotation.EnumerationProperty;
import edu.pku.sei.gefcommon.descriptor.annotation.MethodProperty;
import edu.pku.sei.modeler.model.common.MetaTypedList;
import edu.pku.sei.modeler.model.core.CorePackage;
import edu.pku.sei.modeler.model.uml.CompleteActivities.ParameterEffectKind;
import edu.pku.sei.modeler.model.uml.Dependencies.Dependency;
import edu.pku.sei.modeler.model.uml.InternalStructures.ConnectorEnd;
import edu.pku.sei.modeler.model.xml.XMLUtility;
import edu.pku.sei.modeler.uml.modelHelper.ModelPackage;
import edu.pku.sei.modeler.uml.util.MetaTypedSet;


/**
 * @generated
 * 
 * modified by zsj
 *
 */
public class Parameter extends MultiplicityElement implements IParameter {
	// attributes
	
	protected ParameterDirectionKind direction = ParameterDirectionKind.RETURN;
	
	protected boolean isException;
	
	protected boolean isStream;
	
	protected ParameterEffectKind effect;
	
	
	
	protected String name;
	
	protected VisibilityKind visibility;
	
	protected String qualifiedName;
	
	
	// references
	
	protected MetaTypedList defaultValue;
	
	
	//modified by zsj; change MetaTypedList to Classifier
	protected Classifier type;
	//end
	
	protected MetaTypedList supplierDependency;
	
	protected MetaTypedList end;
	
	//added by zsj
	private int typeId;
	
	public Parameter() {
		this.setLower(1);
		this.setUpper(1);
	}
	
	
	// getters & setters for attributes
	@MethodProperty(id = "PARAMETER_DIRECTION", catalog = "General", name = ModelPackage.PARAMETER_DIRECTION, setter = "setDirection")
	@EnumerationProperty(function = "getAllDirectionKinds")
	public ParameterDirectionKind getDirection() {
		return direction;
	}
	public void setDirection(ParameterDirectionKind newDirection) {
		ParameterDirectionKind olddirection = direction;
		direction = newDirection;
		firePropertyChange(ModelPackage.PARAMETER_DIRECTION, olddirection, newDirection);
	}
	public Object[] getAllDirectionKinds() {
		return ParameterDirectionKind.getAllDirectionKinds();
	}
	@MethodProperty(
			id = "PARAMETER_ISEXCEPTION",
			catalog = "General",
			name = ModelPackage.PARAMETER_ISEXCEPTION,
			setter = "setIsException"
			)
	
	public boolean getIsException() {
		return isException;
	}
	public void setIsException(boolean newIsException) {
		boolean oldisException = isException;
		isException = newIsException;
		firePropertyChange(ModelPackage.PARAMETER_ISEXCEPTION, oldisException, newIsException);
	}
	
	@MethodProperty(
			id = "PARAMETER_ISSTREAM",
			catalog = "General",
			name = ModelPackage.PARAMETER_ISSTREAM,
			setter = "setIsStream"
			)
	
	public boolean getIsStream() {
		return isStream;
	}
	public void setIsStream(boolean newIsStream) {
		boolean oldisStream = isStream;
		isStream = newIsStream;
		firePropertyChange(ModelPackage.PARAMETER_ISSTREAM, oldisStream, newIsStream);
	}
	
	public ParameterEffectKind getEffect() {
		return effect;
	}
	public void setEffect(ParameterEffectKind newEffect) {
		ParameterEffectKind oldeffect = effect;
		effect = newEffect;
		firePropertyChange(ModelPackage.PARAMETER_EFFECT, oldeffect, newEffect);
	}
	
	@MethodProperty(
			id = "PARAMETER_NAME",
			catalog = "General",
			name = ModelPackage.NAMEDELEMENT_NAME,
			setter = "setName"
			)
	
	public String getName() {
		return name;
	}
	public void setName(String newName) {
		String oldname = name;
		name = newName;
		firePropertyChange(ModelPackage.NAMEDELEMENT_NAME, oldname, newName);
	}
	
	@MethodProperty(id = "NAMEDELEMENT_VISIBILITY", catalog = "General", name = ModelPackage.NAMEDELEMENT_VISIBILITY, setter = "setVisibility")
	@EnumerationProperty(function = "getAllVisibilityKinds")
	public VisibilityKind getVisibility() {
		return visibility;
	}
	public void setVisibility(VisibilityKind newVisibility) {
		VisibilityKind oldvisibility = visibility;
		visibility = newVisibility;
		firePropertyChange(ModelPackage.NAMEDELEMENT_VISIBILITY, oldvisibility, newVisibility);
	}
	public Object[] getAllVisibilityKinds() {
		return VisibilityKind.getAllVisibilityKinds();
	}
	@MethodProperty(
			id = "PARAMETER_QUALIFIEDNAME",
			catalog = "General",
			name = ModelPackage.NAMEDELEMENT_QUALIFIEDNAME,
			setter = "setQualifiedName"
			)
	
	public String getQualifiedName() {
		return qualifiedName;
	}
	public void setQualifiedName(String newQualifiedName) {
		String oldqualifiedName = qualifiedName;
		qualifiedName = newQualifiedName;
		firePropertyChange(ModelPackage.NAMEDELEMENT_QUALIFIEDNAME, oldqualifiedName, newQualifiedName);
	}
	
	// getters for references
	
	public MetaTypedList getDefaultValue() {
		if(defaultValue == null) {
			defaultValue = new MetaTypedSet(ValueSpecification.class, this, ModelPackage.PARAMETER_DEFAULTVALUE);
		}
		return defaultValue;
	}
	
	@MethodProperty(id = "TYPEDELEMENT_TYPE", catalog = "General", name = ModelPackage.TYPEDELEMENT_TYPE, setter = "setType")
	@EnumerationProperty(function = "getTypes")
	public Classifier getTypeAsClassifier() {
		if(type == null) {
			type = (Classifier) XMLUtility.xmlInstance.getMetaElementByID(typeId);
		}
		return type;
	}
	
	
	public MetaTypedList getType() {
		return null;
	}

	
	//added by zsj
	public Object[] getTypes() {
		List types = model.getAllTypes();
		return types.toArray();
	}
	
	public void setType(Classifier newType) {
		Classifier oldType = this.type;
		this.type = newType;
		this.firePropertyChange(ModelPackage.TYPEDELEMENT_TYPE, oldType, newType);

	}
	//end 
	
	public MetaTypedList getSupplierDependency() {
		if(supplierDependency == null) {
			supplierDependency = new MetaTypedSet(Dependency.class, this, ModelPackage.NAMEDELEMENT_SUPPLIERDEPENDENCY);
		}
		return supplierDependency;
	}
	
	public MetaTypedList getEnd() {
		if(end == null) {
			end = new MetaTypedSet(ConnectorEnd.class, this, ModelPackage.CONNECTABLEELEMENT_END);
		}
		return end;
	}
	
	// save & load
	public void serialize(Element root) {
		super.serialize(root);
		// attributes
		
		XMLUtility.xmlInstance.serializeAttribute(root, ModelPackage.PARAMETER_DIRECTION, direction.getValue());
		
		XMLUtility.xmlInstance.serializeAttribute(root, ModelPackage.PARAMETER_ISEXCEPTION, isException);
		
		XMLUtility.xmlInstance.serializeAttribute(root, ModelPackage.PARAMETER_ISSTREAM, isStream);
		
		XMLUtility.xmlInstance.serializeNode(root, ModelPackage.PARAMETER_EFFECT, effect);
		
		XMLUtility.xmlInstance.serializeAttribute(root, ModelPackage.NAMEDELEMENT_NAME, name);
		
		if (this.visibility != null) {
			XMLUtility.xmlInstance.serializeAttribute(root, ModelPackage.NAMEDELEMENT_VISIBILITY, this.visibility.getEnumName());
		}
		
		XMLUtility.xmlInstance.serializeAttribute(root, ModelPackage.NAMEDELEMENT_QUALIFIEDNAME, qualifiedName);
		
		// references
		
		XMLUtility.xmlInstance.serializeNodes(root, ModelPackage.PARAMETER_DEFAULTVALUE, defaultValue);
		
		XMLUtility.xmlInstance.serializeNodeNotContain(root, ModelPackage.TYPEDELEMENT_TYPE, type);	

		//end 
		
		XMLUtility.xmlInstance.serializeNodesNotContain(root, ModelPackage.NAMEDELEMENT_SUPPLIERDEPENDENCY, supplierDependency);		
		
		XMLUtility.xmlInstance.serializeNodesNotContain(root, ModelPackage.CONNECTABLEELEMENT_END, end);		
		
	}
	
	public void deSerialize(Element root) {
		super.deSerialize(root);
		// attributes
		
		direction = ParameterDirectionKind.getInstance(XMLUtility.xmlInstance.deSerializeString(root, ModelPackage.PARAMETER_DIRECTION));
		
		isException = XMLUtility.xmlInstance.deSerializeBoolean(root, ModelPackage.PARAMETER_ISEXCEPTION);
		
		isStream = XMLUtility.xmlInstance.deSerializeBoolean(root, ModelPackage.PARAMETER_ISSTREAM);
		
		effect = (ParameterEffectKind)XMLUtility.xmlInstance.deSerializeNode(root, ModelPackage.PARAMETER_EFFECT, this);
		
		name = XMLUtility.xmlInstance.deSerializeString(root, ModelPackage.NAMEDELEMENT_NAME);
		
		visibility = new VisibilityKind(XMLUtility.xmlInstance.deSerializeString(root, ModelPackage.NAMEDELEMENT_VISIBILITY));
		
		qualifiedName = XMLUtility.xmlInstance.deSerializeString(root, ModelPackage.NAMEDELEMENT_QUALIFIEDNAME);
		
		// references
		
		this.getDefaultValue().addAll(XMLUtility.xmlInstance.deSerializeNodes(root, ModelPackage.PARAMETER_DEFAULTVALUE));
		
		this.typeId = XMLUtility.xmlInstance.getIDAttribute(root, ModelPackage.TYPEDELEMENT_TYPE);

		this.setType((Classifier) (XMLUtility.xmlInstance.deSerializeNodeNotContain(root, ModelPackage.TYPEDELEMENT_TYPE, this)));
		
		this.getSupplierDependency().addAll(XMLUtility.xmlInstance.deSerializeNodesNotContain(root, ModelPackage.NAMEDELEMENT_SUPPLIERDEPENDENCY, this));
		
		this.getEnd().addAll(XMLUtility.xmlInstance.deSerializeNodesNotContain(root, ModelPackage.CONNECTABLEELEMENT_END, this));
		
	}
	
	public void dynamicSet(String featureID, Object value) {
		if(featureID == null || "".equals(featureID)) {
			return;
		}
		// attributes
		
		else if(ModelPackage.PARAMETER_DIRECTION.equals(featureID)) {
			direction = (ParameterDirectionKind)value;
		}
		
		else if(ModelPackage.PARAMETER_EFFECT.equals(featureID)) {
			effect = (ParameterEffectKind)value;
		}
		
		else if(ModelPackage.NAMEDELEMENT_VISIBILITY.equals(featureID)) {
			visibility = (VisibilityKind)value;
		}
		
		// references
		
		else if(ModelPackage.TYPEDELEMENT_TYPE.equals(featureID)) {
			//getType().add(value);
			type = (Classifier)value;
		}
		
		else if(ModelPackage.NAMEDELEMENT_SUPPLIERDEPENDENCY.equals(featureID)) {
			getSupplierDependency().add(value);
		}
		
		else if(ModelPackage.CONNECTABLEELEMENT_END.equals(featureID)) {
			getEnd().add(value);
		}
		
		else
			super.dynamicSet(featureID, value);
	}
	
	public String getCustomLabel() {
		final StringBuffer label = new StringBuffer();

		// direction
//		label.append(getDirectionAsString());
//		label.append(" ");

		// name
		label.append(getName());
		label.append(":");

		// type
		label.append(getTypeAsString());
//		label.append(" ");
//
//		// multiplicity
//		label.append(getMultiplicityAsString());
//		label.append(" ");

		// default
		label.append(getDefaultAsString(true));

		// modifier
		// label.append(getPropertiesAsString());

		return label.toString();
	}

	public String getDirectionAsString() {
		return this.direction.getValue();
	}

	/**
	 * 
	 * 
	 * @return
	 */
	public String getTypeAsString() {
		//TODO
		return (this.getTypeAsClassifier() != null) ? this.getTypeAsClassifier().getName() : "";
	}

	/**
	 * 
	 * 
	 * @return
	 */
	public String getMultiplicityAsString() {
		if (getLower() == 1 && getLower() == getUpper()) {
			return "";
		}
		
		
		StringBuffer buffer = new StringBuffer();
		buffer.append("[");

		// special case for [1] and [*]
		int lower = this.getLower();
		int upper = this.getUpper();

		if (lower == upper) {
			buffer.append(lower);
		} else if ((lower == 0) && (upper == -1)) {
			buffer.append("*");
		} else if (upper == -1) {
			buffer.append(lower);
			buffer.append("..*");
		} else {
			buffer.append(lower);
			buffer.append("..");
			buffer.append(upper);
		}

		buffer.append("]");
		return buffer.toString();
	}

	/**
	 * 
	 * 
	 * @return
	 */
	// public String getPropertiesAsString() {
	// StringBuffer buffer = new StringBuffer();
	//
	// // default : unique and not ordered
	// if(this.getisUnique()) {
	// if(this.getisOrdered()) {
	// buffer.append("ordered");
	// } else {
	// buffer.append("");
	// }
	// } else {
	// if(this.getisOrdered()) {
	// buffer.append("ordered, nonunique");
	// } else {
	// buffer.append("nonunique");
	// }
	// }
	// return buffer.toString();
	// }
	/**
	 * generate the label for the Parameter, corresponding to the UML2 notation.
	 * 
	 * @return the label of the parameter
	 */
	public String getLabel() {
		StringBuffer buffer = new StringBuffer();

		// direction
		buffer.append(this.getDirectionAsString());

		// name
		buffer.append(" ");
		buffer.append(this.getName());

		// type
		buffer.append(": ");
		buffer.append(this.getTypeAsString());

		// multiplicity
		buffer.append(" ");
		buffer.append(this.getMultiplicityAsString());

		// default value
		if ((this.getDefaultValue() != null) && !this.getDefaultValue().equals("")) {
			buffer.append("= ");
			buffer.append(this.getDefaultValue());
		}

		// param property
		// String properties = this.getPropertiesAsString();
		// if(!properties.equals("")) {
		// buffer.append("{");
		// buffer.append(properties);
		// buffer.append("}");
		// }

		return buffer.toString();
	}

	/**
	 * Returns the default value as a String
	 * 
	 * @param equalSign
	 *            boolean set to <code>true</code> if the label must have the
	 *            <code>=</code> sign before the default value
	 * @return the default value as a String
	 */
	public String getDefaultAsString(boolean equalSign) {
		String defaultString = "";
		// default value
		if ((this.getDefaultValue() != null) && !this.getDefaultValue().equals("")) {
			if (equalSign) {
				defaultString += "= ";
			}
			defaultString += this.getDefaultValue();
		}
		return "";
	}

	public String toString() {
		return this.getName();
	}
}
 
 
 
 
 